package com.yixun.qfbao.api.service.impl;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import com.yixun.qfbao.constant.StringConstant;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.WriterException;
import com.yixun.qfbao.api.service.SubscriptionApiService;
import com.yixun.qfbao.api.service.ThirdPartyApiService;
import com.yixun.qfbao.apidto.CheckMobileCheckCodeReqDto;
import com.yixun.qfbao.apidto.CheckMobileCheckCodeResDto;
import com.yixun.qfbao.apidto.CreateQRCodeReqDto;
import com.yixun.qfbao.apidto.CreateQRCodeResDto;
import com.yixun.qfbao.apidto.CustomerToM2ReqDto;
import com.yixun.qfbao.apidto.CustomerToM2ResDto;
import com.yixun.qfbao.apidto.GetCPToM2InfoReqDto;
import com.yixun.qfbao.apidto.GetCPToM2InfoResDto;
import com.yixun.qfbao.apidto.GetPremisesByM2ReqDto;
import com.yixun.qfbao.apidto.GetPremisesByM2ResDto;
import com.yixun.qfbao.apidto.GetWeiXinJsTicketReqDto;
import com.yixun.qfbao.apidto.IsM2MerchantReqDto;
import com.yixun.qfbao.apidto.IsM2MerchantResDto;
import com.yixun.qfbao.apidto.SendMobileCheckCodeReqDto;
import com.yixun.qfbao.apidto.SendMobileCheckCodeResDto;
import com.yixun.qfbao.apidto.SendValidateCodeForPwdReqDto;
import com.yixun.qfbao.apidto.SendValidateCodeForPwdResDto;
import com.yixun.qfbao.apidto.SendVerificationCodeReqDto;
import com.yixun.qfbao.apidto.SendVerificationCodeResDto;
import com.yixun.qfbao.config.M2ApiConfig;
import com.yixun.qfbao.constant.WxConstant;
import com.yixun.qfbao.mapper.SmsHistoryMapper;
import com.yixun.qfbao.model.ChannelToM2Res;
import com.yixun.qfbao.model.Company;
import com.yixun.qfbao.model.PartnerInfo;
import com.yixun.qfbao.model.Subscription;
import com.yixun.qfbao.model.dto.ChannelToM2ResDto;
import com.yixun.qfbao.model.dto.CompanyDto;
import com.yixun.qfbao.model.dto.PartnerInfoDto;
import com.yixun.qfbao.model.dto.SmsHistoryDto;
import com.yixun.qfbao.model.dto.ValidateCodeDto;
import com.yixun.qfbao.model.enums.DelFlagEnum;
import com.yixun.qfbao.model.enums.M2RequestEnum;
import com.yixun.qfbao.model.enums.SMSTypeEnum;
import com.yixun.qfbao.model.enums.SendStatusEnum;
import com.yixun.qfbao.model.enums.SystemIdEnum;
import com.yixun.qfbao.service.CompanyService;
import com.yixun.qfbao.service.PartnerInfoService;
import com.yixun.qfbao.service.SmsSettingService;
import com.yixun.qfbao.service.ValidateCodeService;
import com.yixun.qfbao.util.DateStyle;
import com.yixun.qfbao.util.DateUtils;
import com.yixun.qfbao.util.EncryptUtil;
import com.yixun.qfbao.util.HttpApi;
import com.yixun.qfbao.util.PorxyResult;
import com.yixun.qfbao.util.PorxyUtil;
import com.yixun.qfbao.util.QRCodeUtil;
import com.yixun.qfbao.util.QiNiuUtil;
import com.yixun.qfbao.util.RedisUtil;
import com.yixun.qfbao.util.SMSUtil;
import com.yixun.qfbao.util.exception.TServerException;
import com.yixun.qfbao.weappmessage.WeAppMessageProperties;
import com.yixun.qfbao.xf.model.CustomerPremises;
import com.yixun.qfbao.xf.model.Premises;
import com.yixun.qfbao.xf.model.dto.CustomerPremisesDto;
import com.yixun.qfbao.xf.model.dto.PremisesDto;
import com.yixun.qfbao.xf.model.enums.MobileCheckEnum;
import com.yixun.qfbao.xf.model.enums.ResultEnum;
import com.yixun.qfbao.xf.model.enums.TempTypeEnum;
import com.yixun.qfbao.xf.service.CustomerPremisesService;
import com.yixun.qfbao.xf.service.PremisesService;

import sun.misc.BASE64Encoder;

/**
 * [文件名称]<br>
 * ThirdPartyApiService.java<br>
 * <br>
 * [文件描述]<br>
 * third party interface<br>
 * <br>
 * 第三方接口 2017-11-27<br>
 * 
 * @author jzliu
 * @version 1.00
 */
@Service
public class ThirdPartyApiServiceImpl implements ThirdPartyApiService {
	
	private static final Logger logger = LoggerFactory.getLogger(ThirdPartyApiServiceImpl.class);

	@Autowired
	private M2ApiConfig m2ApiConfig;
	@Autowired
	private CompanyService companyService;
	@Autowired
	private CustomerPremisesService customerPremisesService;
	@Autowired
	private PremisesService premisesService;
	@Autowired
	private PartnerInfoService partnerInfoService;
	@Autowired
	private ValidateCodeService validateCodeService;
	@Autowired
	private SubscriptionApiService subscriptionApiService;
	@Autowired
	private WeAppMessageProperties weAppMessageProperties;
	@Autowired
	private SmsSettingService smsSettingService;
	@Autowired
	private SMSUtil smsUtil;
	@Autowired
	private SmsHistoryMapper smsHistoryMapper;
	

	
	/**
	 * 发送验证码
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
//	@Transactional(rollbackFor = Exception.class)
	public SendVerificationCodeResDto sendVerificationCode(SendVerificationCodeReqDto reqDto) {
		SendVerificationCodeResDto resDto = new SendVerificationCodeResDto();
		String domain = reqDto.getDomain();
		String code = reqDto.getCode();
		boolean message = reqDto.isSendMsgFlag();

		// 发送成功,验证存库并返回验证码
		ValidateCodeDto dto = new ValidateCodeDto();
		dto.setAccountNo(reqDto.getPhone());
		dto.setValidateCode(code);
		if (message) {
			dto.setStatus(SendStatusEnum.SUCCESS.getNo());
		} else {
			dto.setStatus(SendStatusEnum.FAILURE.getNo());
		}
		dto.setDomain(domain);
		dto.setSystemId(reqDto.getLoginType());
		if (validateCodeService.create(dto) <= 0) {
			throw new RuntimeException("保存验证码失败");
		}
		
		resDto.setResult(ResultEnum.SUCCESS.getNo());
		resDto.setResultMsg("短信发送成功，请查收");
		return resDto;
	}
	
	/**
	 * @description
	 * @author sangtao
	 * @date 2017/12/1
	 * @param reqDto
	 **/
	@Override
	public SendValidateCodeForPwdResDto sendValidateCodeForPwd(SendValidateCodeForPwdReqDto reqDto) {
		SendValidateCodeForPwdResDto resDto = new SendValidateCodeForPwdResDto();
		PartnerInfoDto partnerInfo = new PartnerInfoDto();
		partnerInfo.setPhone(reqDto.getPhone());
		partnerInfo.setDomain(reqDto.getDomain());
		partnerInfo.setSystemId(reqDto.getLoginType());
		String code = validateCodeService.sendValidateCodeForPwd(partnerInfo,reqDto.getCompanyUuid());
		if (code != null) {
			resDto.setResult(ResultEnum.SUCCESS.getNo());
		} else {
			resDto.setResult(ResultEnum.FAIL.getNo());
		}
		return resDto;
	}
	
	/**
	 * （2）生产微信二维码
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public CreateQRCodeResDto createQRCode(CreateQRCodeReqDto reqDto) {
		CreateQRCodeResDto resDto = new CreateQRCodeResDto();
		try {
			BufferedImage bufferedImage = QRCodeUtil.createQRCode(reqDto.getContent());
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ImageIO.write(bufferedImage, "png", out);
			byte[] b = out.toByteArray();
			BASE64Encoder encoder = new BASE64Encoder();
			String base64 = "data:image/png;base64," + encoder.encode(b);
			System.out.println(base64);
			resDto.setQrCode(base64);
			resDto.setResult(ResultEnum.SUCCESS.getNo());
			return resDto;
		} catch (WriterException e) {
			logger.error("生成二维码失败", e);
		} catch (IOException e) {
			logger.error("生成二维码失败", e);
		}
		resDto.setResult(ResultEnum.FAIL.getNo());
		resDto.setResultMsg("生成二维码失败");
		return resDto;
	}
	
	/**
	 * 获取生成的二维码上传至七牛的链接
	 * @param content
	 * @return
	 */
	@Override
	public String getQrCodeQiniuUrl(String content) {
		try {
			BufferedImage bufferedImage = QRCodeUtil.createQRCode(content);
			return uploadToQiniu(bufferedImage);
		} catch (WriterException e) {
			logger.error("生成二维码失败", e);
		} catch (IOException e) {
			logger.error("生成二维码失败", e);
		}
		return null;
	}
	
	/**
	 * 
	 * @param bufferedImage
	 * @return
	 * @throws IOException 
	 */
	private String uploadToQiniu(BufferedImage bufferedImage) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ImageIO.write(bufferedImage, "png", out);
		byte[] b = out.toByteArray();
		String fileKey = QiNiuUtil.getFileKey(".png");
		//将文件存储到七牛云
		QiNiuUtil.upload(b, fileKey, QiNiuUtil.STORE_BUCKET);
		return QiNiuUtil.FILE_VIEWURL + fileKey;
	}
	
	/**
	 * （3） 获取微信appid
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public Map<String, String> getWeiXinAppid(GetWeiXinJsTicketReqDto reqDto) {
		Map<String, String> map = new HashMap<String, String>();
		String systemId = reqDto.getLoginType();
		if(systemId.equals(SystemIdEnum.DEVELOPERS.getCode())){
			systemId = SystemIdEnum.ASSISTANT.getCode();
		}else if(systemId.equals(SystemIdEnum.AGENCY_WEB.getCode())){
			systemId = SystemIdEnum.AGENCY_h5.getCode();
		}
		Subscription subscription = subscriptionApiService.getSubscriptionInfo(reqDto.getCompanyUuid(),reqDto.getDomain(), systemId);

		map.put("appId", subscription.getAppId());
		map.put("appSecret", subscription.getAppSecret());
		map.put("companyUuid",subscription.getCompanyUuid());
		
		return map;
	}
	
	/**
	 * （3） 获取微信js_ticket
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public Map<String,String> getWeiXinJsTicket(GetWeiXinJsTicketReqDto reqDto) {
		String jsTicket = null;
		try {
			Map<String, String> mapKay = new HashMap<String, String>(2);
			mapKay.put("appId", reqDto.getAppId());
			mapKay.put("appSecret", reqDto.getAppSecret());
			// 获取js_ticket
			Map<String, String> jtMap = jsTicket(mapKay);
			return jtMap;
		} catch (Exception e) {
			logger.error("获取微信授权码失败: {}", e);
		}
		return null;
	}

    @Override
    public Map<String, String> getWeiXinJsTicketByToken(String accessToken) {
        String jsTicket = null;
        try {
            // 获取js_ticket
            Map<String, String> jtMap = jsTicketByToken(accessToken);
            return jtMap;
        } catch (Exception e) {
            logger.error("获取微信授权码失败: {}", e);
        }
        return null;
    }

    /**
	 * 从微信接口获取js_ticket
	 * 
	 * @param appIdMap
	 * @return
	 */
	private Map<String, String> jsTicket(Map<String, String> appIdMap) {
		Map<String, String> map = new HashMap<String, String>(2);
		try {
			Map<String, String> token = getAccessToken(appIdMap);
			String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
			String access_token = token.get("access_token");
			if (null != access_token) {
				url = url.replace("ACCESS_TOKEN", token.get("access_token"));
			}
			PorxyResult porxyResult = PorxyUtil.getPorxy(url);
			JSONObject resultJson = new JSONObject();
			resultJson = JSONObject.parseObject(porxyResult.getContext());
			map.put("access_token", token.get("access_token"));
			map.put("jsapi_ticket", resultJson.getString("ticket"));
			Long expiresIn = Calendar.getInstance().getTimeInMillis() + resultJson.getLongValue("expires_in") *1000;
			map.put("lost_time",expiresIn.toString());
		} catch (Exception e) {
			logger.error("获取jsapi_ticket出错: {}", e);
		}
		return map;
	}

	/**
	 * 从微信接口获取js_ticket
	 *
	 * @param accessToken
	 * @return
	 */
	private Map<String, String> jsTicketByToken(String accessToken) {
		Map<String, String> map = new HashMap<String, String>(2);
		try {
			String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
			if (null != accessToken) {
				url = url.replace("ACCESS_TOKEN", accessToken);
			}
			PorxyResult porxyResult = PorxyUtil.getPorxy(url);
			JSONObject resultJson = new JSONObject();
			resultJson = JSONObject.parseObject(porxyResult.getContext());
			map.put("access_token", accessToken);
			map.put("jsapi_ticket", resultJson.getString("ticket"));
			Long expiresIn = Calendar.getInstance().getTimeInMillis() + resultJson.getLongValue("expires_in") *1000;
			map.put("lost_time",expiresIn.toString());
		} catch (Exception e) {
			logger.error("获取jsapi_ticket出错: {}", e);
		}
		return map;
	}
	
	/**
	 * 获取account_token
	 * 
	 * @param appIdMap
	 * @return
	 */
	private Map<String, String> getAccessToken(Map<String, String> appIdMap) {
		Map<String, String> map = new HashMap<String, String>(2);
		try {
			String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
			url = url.replace("APPID", appIdMap.get("appId"));
			url = url.replace("APPSECRET", appIdMap.get("appSecret"));
			PorxyResult porxyResult = PorxyUtil.getPorxy(url);
			JSONObject resultJson = new JSONObject();
			resultJson = JSONObject.parseObject(porxyResult.getContext());
			map.put("access_token", resultJson.getString("access_token"));
		} catch (Exception e) {
			logger.error("获取access_token出错: {}", e);
		}
		return map;
	}

    /**
     * 获取account_token
     *
     * @return
     */
    public String getAccessTokenDefault(String domain, String companyUuid, String loginType) {
        try {
            //查询商户对应的微信appID和appSecret
            GetWeiXinJsTicketReqDto getWeiXinJsTicketReqDto = new GetWeiXinJsTicketReqDto();
            getWeiXinJsTicketReqDto.setDomain(domain);
            getWeiXinJsTicketReqDto.setCompanyUuid(companyUuid);
            getWeiXinJsTicketReqDto.setLoginType(loginType);
            Map<String, String> appIdMap = getWeiXinAppid(getWeiXinJsTicketReqDto);
			logger.info("appIdMap = " + JSONObject.toJSONString(appIdMap));
            if(appIdMap == null) {
                throw new TServerException("商户未配置微信信息！");
            }
            String url = WxConstant.ACCESS_TOKEN_URL;
            url = url.replace("APPID", appIdMap.get("appId"));
            url = url.replace("APPSECRET", appIdMap.get("appSecret"));
			logger.info("get token url = " + url);
            PorxyResult porxyResult = PorxyUtil.getPorxy(url);
            JSONObject resultJson = JSONObject.parseObject(porxyResult.getContext());
            logger.info("token result json, {}", JSONObject.toJSONString(resultJson));
			logger.info("access_token变更: 公司Uuid = " + companyUuid + ", 系统类型 = " + loginType + ", access_token = " + resultJson.getString("access_token") + ", 变更时间 = " + DateUtils.DateToString(Calendar.getInstance().getTime(), DateStyle.YYYY_MM_DD_HH_MM_SS));
            return resultJson.getString("access_token");
        } catch (Exception e) {
            logger.error("获取access_token出错: {}", e);
        }
        return null;
    }

	/**
	 * 获取account_token
	 *
	 * @return
	 */
	public String getWeAppAccessTokenDefault(String loginType) {
		try {
			String url = WxConstant.ACCESS_TOKEN_URL;
			url = url.replace("APPID", weAppMessageProperties.getWeAppAgencyMessageAppId());
			url = url.replace("APPSECRET", weAppMessageProperties.getWeAppAgencyMessageAppSecret());
			logger.info("get token url = " + url);
			PorxyResult porxyResult = PorxyUtil.getPorxy(url);
			JSONObject resultJson = JSONObject.parseObject(porxyResult.getContext());
			logger.info("token result json, {}", JSONObject.toJSONString(resultJson));
			logger.info("小程序 access_token变更: " + "access_token = " + resultJson.getString("access_token") + ", 变更时间 = " + DateUtils.DateToString(Calendar.getInstance().getTime(), DateStyle.YYYY_MM_DD_HH_MM_SS));
			return resultJson.getString("access_token");
		} catch (Exception e) {
			logger.error("获取小程序access_token出错: {}", e);
		}
		return null;
	}
	
	/**
	 * （5） 获取转客信息
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public GetCPToM2InfoResDto getCPToM2Info(GetCPToM2InfoReqDto reqDto) {
		GetCPToM2InfoResDto resDto = new GetCPToM2InfoResDto();
		
		// 查询客户信息
		CustomerPremises cusPre = customerPremisesService.selectById(reqDto.getCusPreId());
		if (cusPre == null) {
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("未查到客户信息!");
			return resDto;
		}
		// 查询楼盘名称
		Premises premises = premisesService.selectSimpleById(cusPre.getPremisesId());
		if (premises == null) {
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("未查到楼盘信息!");
			return resDto;
		}
		resDto.setMobile(cusPre.getMobile());
		resDto.setName(cusPre.getName());
		resDto.setPremisesName(premises.getName());
		resDto.setIsToM2(cusPre.getIsToM2());
		if (StringUtils.isBlank(premises.getProjectCodeM2())) {
			// 当M2项目编号为空时表示非M2合作商户，不能转客
			resDto.setIsToM2("2");
		}
		resDto.setCustomerStatus(cusPre.getCustomerStatus());
		resDto.setResult(ResultEnum.SUCCESS.getNo());
		return resDto;
	}
	
	/**
	 * （6） 获取M2楼盘
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public GetPremisesByM2ResDto getPremisesByM2(GetPremisesByM2ReqDto reqDto) {
		GetPremisesByM2ResDto resDto = new GetPremisesByM2ResDto();
		
		// 查询合作机构
		PartnerInfo pi = partnerInfoService.selectById(strinToLong(reqDto.getUserId()));
		if (pi == null) {
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("未获取到合作机构!");
			return resDto;
		}
		long companyId = pi.getHigherid();
		Company company = companyService.selectById(companyId);
		if (company == null) {
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("未获取到商户!");
			return resDto;
		}
		// M2的商户号
		String merchantCode = company.getMerchantCode();
		if (StringUtils.isBlank(merchantCode)) {
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("未获取到M2的商户号!");
			return resDto;
		}
		Map map = new HashMap(4);
		map.put("merchantCode", merchantCode);
		map.put("token", merchantCode);
		map.put("version", null);
		// 生成签名
		String signStr = EncryptUtil.createLinkString(map);
		String sign = EncryptUtil.Encrypt(signStr, "MD5");
		map.put("sign", sign);
		// 将map转换成json
		JSONObject json = new JSONObject(map);
		try {
			// 拼接接口地址
			String url = m2ApiConfig.getM2RequestUrl() + M2RequestEnum.QUERY_PROJECT.getNo();
			// 从M2系统获取楼盘信息
			String resStr = HttpApi.doPostUrl(url, json);
			if (StringUtils.isBlank(resStr)) {
				resDto.setResult(ResultEnum.FAIL.getNo());
				resDto.setResultMsg("获取M2楼盘信息失败!");
				return resDto;
			}
			JSONObject jsonObject = JSONObject.parseObject(resStr);
			String resDataStr = jsonObject.getString("resData");
			JSONObject resDataJson = JSONObject.parseObject(resDataStr);
			String result = resDataJson.getString("result");
			if (!ResultEnum.SUCCESS.getNo().equals(result)) {
				resDto.setResult(ResultEnum.FAIL.getNo());
				resDto.setResultMsg("获取M2楼盘信息失败!");
				return resDto;
			}
			String projectStr = resDataJson.getString("mcProjectList");
			JSONArray mcProjectList = JSONObject.parseArray(projectStr);
			if (mcProjectList.size() > 0) {
				// 获取商户下已同步的M2楼盘
				PremisesDto premisesDto = new PremisesDto();
				premisesDto.setCompanyId(companyId);
				List<Premises> premisesList = premisesService.selectListByDto(premisesDto);
				
				// 判断是否通不过改楼盘
				for (int ii = 0; ii < mcProjectList.size(); ii++) {
					JSONObject projectObject = (JSONObject)mcProjectList.get(ii);
					projectObject.put("synFlag", "F");
					String projectCode = projectObject.getString("projectCode");
					
					if (null != premisesList && premisesList.size() > 0) {
						for (Premises premises : premisesList) {
							String projectCodeM2 = premises.getProjectCodeM2();
							if (projectCode.equals(projectCodeM2)) {
								projectObject.put("synFlag", "T");
							}
						}
					}
				}
			}
			resDto.setProjectList(mcProjectList);
			resDto.setResult(ResultEnum.SUCCESS.getNo());
		} catch (Exception e) {
			logger.error("获取M2楼盘信息失败: {}", e);
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("获取M2楼盘信息失败!");
		}
		return resDto;
	}
	
	/**
	 * （7） 转客
	 * 
	 * @param reqDto
	 * @return
	 */
	@Override
	public CustomerToM2ResDto customerToM2(CustomerToM2ReqDto reqDto) {
		CustomerToM2ResDto resDto = new CustomerToM2ResDto();
		
		try {
			List<String> idList = new ArrayList<String>();
			String[] ids = reqDto.getCusPreId().split(",");
			for (int i = 0; i < ids.length; i++) {
				idList.add(ids[i]);
			}
			List<Map<String, String>> mapList = new ArrayList<Map<String, String>>();
			// 查询数据主体
			CustomerPremisesDto entity = new CustomerPremisesDto();
			entity.setCustomerIds(idList);
			List<CustomerPremises> list = customerPremisesService.selectListByIds(entity);
			String projectCode = "errorPro";
			for (CustomerPremises dto : list) {
				Premises premises = premisesService.selectSimpleById(dto.getPremisesId());
				if (null != premises) {
					projectCode = premises.getProjectCodeM2();
				}
				Map<String, String> map = new HashMap<String, String>(5);
				map.put("recommendedChannelId", dto.getId().toString());
				map.put("userName", dto.getName());
				map.put("phone", dto.getMobile());
				map.put("projectCode", projectCode);
				map.put("remark", reqDto.getRemark());
				mapList.add(map);
			}
			// 组装接口入参
			JSONObject json = new JSONObject();
			// 版本号（备用）
			json.put("version", "");
			// token（备用）
			json.put("token", "");
			// 签名（备用）
			json.put("sign", "");
			json.put("customerList", mapList);
			// 访问m2接口
			String url = m2ApiConfig.getM2RequestUrl() + M2RequestEnum.CUS_TOM2.getNo();
			String str = HttpApi.doPostUrl(url, json);
			JSONObject obj = JSONObject.parseObject(str);
			// 解析返回数据
			ChannelToM2ResDto resM2 = JSONObject.parseObject(obj.get("resData") + "", ChannelToM2ResDto.class);
			if (!ResultEnum.SUCCESS.getNo().equals(resM2.getResult())) {
				resDto.setResult(ResultEnum.FAIL.getNo());
				resDto.setResultMsg("转客失败：" + resM2.getErrorMsg());
				return resDto;
			}
			// 获取未成功数据
			List<ChannelToM2Res> failList = resM2.getFailList();
			if (null != failList) {
				// 筛选转客成功的客户ID
				for (ChannelToM2Res res : failList) {
					Iterator<String> it = idList.iterator();
					while (it.hasNext()) {
						String temp = it.next();
						if (temp.equals(res.getM2Id().toString())) {
							it.remove();
						}
					}
				}
			}
			// 将转客成功的数据标识为已转客
			if (idList.size() > 0) {
				CustomerPremisesDto update = new CustomerPremisesDto();
				update.setCustomerIds(idList);
				// 已转客
				update.setIsToM2("1");
				customerPremisesService.updateByIds(update);
			}
			resDto.setFailList(failList);
			resDto.setTotal(resM2.getTotal());
			resDto.setSuccessNum(resM2.getSuccessNum());
			resDto.setFailNum(resM2.getFailNum());
			resDto.setResult(ResultEnum.SUCCESS.getNo());
		} catch (Exception e) {
			logger.error("转客失败: {}", e);
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("转客失败");
		}
		return resDto;
	}
	
	/**
	 * String转Long
	 * 
	 * @param field
	 * @return Long
	 */
	private Long strinToLong(String field) {
		return StringUtils.isBlank(field) ? null : Long.parseLong(field);
	}

	@Override
	public IsM2MerchantResDto isM2Merchant(IsM2MerchantReqDto reqDto) {
		IsM2MerchantResDto res = new IsM2MerchantResDto();
		CompanyDto cDto = new CompanyDto();
		cDto.setDomain(reqDto.getDomain());
		cDto.setCompanyUuid(reqDto.getCompanyUuid());
		cDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		Company company = companyService.selectBy(cDto);
		if(company!=null){
			if(StringUtils.isNotBlank(company.getMerchantCode())){
				res.setM2Merchant(true);
			}else{
				res.setM2Merchant(false);
			}
			res.setResult(ResultEnum.SUCCESS.getNo());
			res.setResultMsg("操作成功");
		}else{
			res.setResult(ResultEnum.FAIL.getNo());
			res.setResultMsg("查询公司失败");
		}
		return res;
	}

	@Override
	public SendMobileCheckCodeResDto sendMobileCheckCode(SendMobileCheckCodeReqDto reqDto) {
		SendMobileCheckCodeResDto resDto = new SendMobileCheckCodeResDto();
		Long id = reqDto.getId();
		if(Objects.isNull(id)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("报备记录不存在!");
			return resDto;
		}
		CustomerPremises customerPremises = customerPremisesService.selectById(id);
		if(Objects.isNull(customerPremises)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("报备记录不存在!");
			return resDto;
		}
		/*
		if(MobileCheckEnum.TYPE_01.getNo().equals(customerPremises.getMobileCheck())){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("号码已验真!");
			return resDto;
		}
		*/
		String mobile = customerPremises.getMobile();
		if(Objects.isNull(mobile) || mobile.indexOf(StringConstant.THREE_STAR) > 0){
			// 为空或者为隐号,不能发送短信
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("号码错误,不能发送短信!");
			return resDto;
		}

		Long companyId = customerPremises.getCompanyId();
		Company company = companyService.selectById(companyId);
		if(Objects.isNull(company)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("无效公司,不能发送短信!");
			return resDto;
		}

		String checkCodeKey = id + "-" + mobile;
		String checkCode = RedisUtil.get(checkCodeKey, String.class);
		if(StringUtils.isBlank(checkCode)){
			// 发送新的验证码
			checkCode = Integer.toString(new Random().nextInt(9000)+1000);
			RedisUtil.setEx(checkCodeKey, checkCode, 10, TimeUnit.MINUTES);
		}

		Premises premises = premisesService.selectSimpleById(customerPremises.getPremisesId());
		if(Objects.isNull(premises)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("无效楼盘,不能发送短信!");
			return resDto;
		}
		logger.info("到访验真记录: {}, 验真短信验证码: {}", checkCodeKey, checkCode);
		//获取短信设置
		Map<String, String> smsSettingMap = smsSettingService.getSmsTempSetting(companyId, TempTypeEnum.TMPE_0001.getNo());
		Map<String,String> qfSmsMap = new HashMap<>();
		qfSmsMap.put("key1", checkCode);
		qfSmsMap.put("key2", premises.getName());
		//发送消息
		Map<String, Object> returnMap = smsUtil.sendQFTempMessage(mobile, smsSettingMap, qfSmsMap);
		boolean sendStatus = (Boolean) returnMap.get("sendStatus");
		String sendRes = String.valueOf(returnMap.get("sendRes"));
		//添加进历史表
		SmsHistoryDto history = new SmsHistoryDto();
		String tempContent = smsSettingMap.get("tempContent");
		tempContent = tempContent.replaceAll("\\{Param\\}", "%s");
		tempContent = String.format(tempContent, checkCode, premises.getName());
		history.setContent(tempContent);
		history.setReceiver(mobile);
		if(company !=null && company.getId() != null){
			history.setMerchantId(company.getId());
		}else{
			history.setMerchantId(0L);
		}
		history.setSender("qiaofang");
		if(null != smsSettingMap) {
			history.setSender(smsSettingMap.get("userName"));
		}
		history.setRemark(SMSTypeEnum.TYPE_16.getDes());
		history.setCreateTime(new Date());
		history.setCreateUserId(0L);
		String state = sendStatus == true ? SendStatusEnum.SUCCESS.getNo():SendStatusEnum.FAILURE.getNo();
		history.setSendStatus(state);
		history.setSendRes(sendRes);
		smsHistoryMapper.add(history);

		resDto.setResult(ResultEnum.SUCCESS.getNo());
		resDto.setResultMsg("短信已发送成功!");
		return resDto;
	}

	@Override
	public CheckMobileCheckCodeResDto checkMobileCheckCode(CheckMobileCheckCodeReqDto reqDto) {
		CheckMobileCheckCodeResDto resDto = new CheckMobileCheckCodeResDto();
		Long id = reqDto.getId();
		if(Objects.isNull(id)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("报备记录不存在!");
			return resDto;
		}
		CustomerPremises customerPremises = customerPremisesService.selectById(id);
		if(Objects.isNull(customerPremises)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("报备记录不存在!");
			return resDto;
		}
		String mobile = customerPremises.getMobile();
		String checkCodeKey = id + "-" + mobile;
		String checkCode = RedisUtil.get(checkCodeKey, String.class);
		logger.info("check mobile check code, checkCodeKey: {}, check code: {}", checkCodeKey, checkCode);
		if(StringUtils.isBlank(checkCode)){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("验证码错误,请重新获取!");
			return resDto;
		}
		if(!checkCode.equals(reqDto.getCheckCode())){
			resDto.setResult(ResultEnum.FAIL.getNo());
			resDto.setResultMsg("验证码错误,请重新输入!");
			return resDto;
		}

		// 通过校验,标记报备校验状态
		CustomerPremisesDto dto = new CustomerPremisesDto();
		dto.setId(customerPremises.getId());
		dto.setMobileCheck(MobileCheckEnum.TYPE_01.getNo());
		dto.setLastCheckTime(new Date());
		customerPremisesService.updateStatus(dto);

		// 删除验证码Key
		RedisUtil.delete(checkCodeKey);

		resDto.setResult(ResultEnum.SUCCESS.getNo());
		resDto.setResultMsg("验证成功!");
		return resDto;

	}

}
